package com.jacars.biz.user.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.jacars.biz.user.dao.model.JsptRoleMenu;
import com.jacars.biz.user.dao.service.JsptMenuService;
import com.jacars.biz.user.dao.service.JsptRoleMenuService;
import com.jacars.common.annotation.LoginUser;
import com.jacars.common.api.PageResult;
import com.jacars.common.api.Result;
import com.jacars.common.constant.CommonConstant;
import com.jacars.common.model.JsptMenu;
import com.jacars.common.model.JsptRole;
import com.jacars.common.model.JsptUser;
import com.jacars.common.utils.FuncUtil;
import com.jacars.db.support.Condition;
import com.jacars.db.support.Query;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

import javax.websocket.server.PathParam;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 作者 owen E-mail: 624191343@qq.com
 */
@RestController
@Api(tags = "菜单模块api")
@Slf4j
@RequestMapping("/menus")
public class MenuController {
    @Autowired
    private JsptMenuService menuService;

    @Autowired
    private JsptRoleMenuService jsptRoleMenuService;

    @ApiOperation(value = "查询所有菜单")
    @GetMapping("/findAlls")
    public PageResult<JsptMenu> findAlls() {
        List<JsptMenu> list = menuService.findAll();
        return PageResult.succeed(list, FuncUtil.toLong(list.size()));
        //return PageResult.<JsptMenu>builder().data(list).code(0).count((long) list.size()).build();
    }

    @ApiOperation(value = "查询所有一级菜单")
    @GetMapping("/findOnes")
    public PageResult<JsptMenu> findOnes() {
        List<JsptMenu> list = menuService.findOnes();
        return PageResult.<JsptMenu>builder().data(list).code(0).count((long) list.size()).build();
    }



    /**
     * 当前登录用户的菜单
     *
     * @return
     */
    @GetMapping("/routes")
    @ApiOperation(value = "查询当前用户菜单")
    public Result<List<JsptMenu>> findMyMenu(@LoginUser JsptUser user) {
        List<JsptRole> roles = user.getRoles();
        if (CollectionUtil.isEmpty(roles)) {
            return Result.succeed("succ");
        }
        List<JsptMenu> menus = menuService.findByRoleCodes(roles.stream().map(JsptRole::getRoleAlias).collect(Collectors.toSet()), CommonConstant.MENU);
        return Result.succeed(treeBuilder(menus));
    }

    /**
     * 前端按钮数据
     * 目前的数据，组织buttons树的时候，有问题。
     */
    @GetMapping("/buttons")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "前端按钮数据", notes = "前端按钮数据")
    public Result<List<JsptMenu>> buttons(@LoginUser JsptUser user) {
        List<JsptRole> roles = user.getRoles();
        if (CollectionUtil.isEmpty(roles)) {
            return Result.succeed();
        }
        List<JsptMenu> menus = menuService.buttons(roles.parallelStream().map(JsptRole::getRoleAlias).collect(Collectors.toSet()), CommonConstant.PERMISSION);

        return Result.succeed(menus);
    }

    /**
     * 当前登录用户的菜单
     *
     * @return
     */
    @GetMapping("/menuTree")
    @ApiOperation(value = "查询当前用户菜单")
    public Result<List<JsptMenu>> menuTree() {
        List<JsptMenu> menus = menuService.list();
        return Result.succeed(treeBuilder(menus));
    }

    /**
     * 当前登录用户的菜单
     *
     * @return
     */
    @GetMapping("/menuPage")
    @ApiOperation(value = "查询当前用户菜单")
    public PageResult<JsptMenu> menuPage(JsptMenu jsptMenu, Query query) {
        IPage<JsptMenu> page = menuService.page(Condition.getPage(query), Condition.getQueryWrapper(jsptMenu));
        List<JsptMenu> menus = page.getRecords();
        long count = menus.stream().filter(k -> k.getCategory().equals(1)).count();
        long count1 = FuncUtil.toLong(menus.size());
        return PageResult.succeed(treeBuilder(menus), count1);
    }

    /**
     * 当前登录用户的菜单
     *
     * @return
     */
    @GetMapping("/topMenu")
    @ApiOperation(value = "查询当前用户菜单")
    public Result<List<JsptMenu>> topMenu() {
        List<JsptMenu> menus = menuService.list(Wrappers.<JsptMenu>lambdaQuery().eq(JsptMenu::getCategory, 1));
        return Result.succeed(treeBuilder(menus));
    }

    /**
     * 当前登录用户的菜单
     *
     * @return
     */
    @GetMapping("/menuButtonTree")
    @ApiOperation(value = "查询当前用户菜单")
    public Result<List<JsptMenu>> topMenu2() {
        List<JsptMenu> menus = menuService.list();
        return Result.succeed(treeBuilder(menus));
    }


    /**
     * 当前登录用户的菜单
     *
     * @return
     */
    @GetMapping("/detail")
    @ApiOperation(value = "查询当前用户菜单")
    public Result<JsptMenu> detail(@PathParam("id") String id) {
        JsptMenu menus = menuService.detail(id);
        return Result.succeed(menus);
    }

    /**
     * 添加菜单 或者 更新
     *
     * @param menu
     * @return
     */
    @ApiOperation(value = "新增菜单")
    @PostMapping("create")
    public Result create(@RequestBody JsptMenu menu) {
        try {
            if (menu.getParentId() == null) {
                menu.setParentId(-1L);
            }
            menuService.save(menu);
            return Result.succeed("操作成功");
        } catch (Exception ex) {
            log.error("memu-saveOrUpdate-error", ex);
            return Result.failed("操作失败");
        }
    }

    @ApiOperation(value = "更新菜单")
    @PostMapping("update")
    public Result update(@RequestBody JsptMenu menu) {
        try {
            if (menu.getParentId() == null) {
                menu.setParentId(-1L);
            }
            menuService.updateById(menu);
            return Result.succeed("操作成功");
        } catch (Exception ex) {
            log.error("memu-saveOrUpdate-error", ex);
            return Result.failed("操作失败");
        }
    }

    /**
     * 删除菜单
     *
     * @param ids
     */
    @ApiOperation(value = "删除菜单")
    @PostMapping("/remove/{ids}")
    public Result delete(@PathVariable List<Long> ids) {
        try {
            menuService.removeByIds(ids);
            return Result.succeed("操作成功");
        } catch (Exception ex) {
            log.error("memu-delete-error", ex);
            return Result.failed("操作失败");
        }
    }

    @ApiOperation(value = "根据roleId获取对应的菜单")
    @GetMapping("/{roleId}/menus")
    public List<Map<String, Object>> findMenusByRoleId(@PathVariable Long roleId) {
        Set<Long> roleIds = new HashSet<>();
        roleIds.add(roleId);
        //获取该角色对应的菜单
        List<JsptMenu> roleMenus = menuService.findByRoles(roleIds);
        //全部的菜单列表
        List<JsptMenu> allMenus = menuService.findAll();
        List<Map<String, Object>> authTrees = new ArrayList<>();

        Map<Long, JsptMenu> roleMenusMap = roleMenus.stream().collect(Collectors.toMap(JsptMenu::getId, SysMenu -> SysMenu));

        for (JsptMenu jsptMenu : allMenus) {
            Map<String, Object> authTree = new HashMap<>();
            authTree.put("id", jsptMenu.getId());
            authTree.put("name", jsptMenu.getName());
            authTree.put("pId", jsptMenu.getParentId());
            authTree.put("open", true);
            authTree.put("checked", false);
            if (roleMenusMap.get(jsptMenu.getId()) != null) {
                authTree.put("checked", true);
            }
            authTrees.add(authTree);
        }
        return authTrees;
    }

    @ApiOperation(value = "根据roleId获取对应的菜单")
    @GetMapping("selectedMenuByRoleId")
    public Result<List<String>> roletreekeys(Long roleId) {
        Set<Long> roleIds = new HashSet<>();
        roleIds.add(roleId);

        List<JsptRoleMenu> list = jsptRoleMenuService.list(Wrappers.<JsptRoleMenu>lambdaQuery().eq(JsptRoleMenu::getRoleId, roleId));

        List<String> collect = list.stream().map(k -> FuncUtil.toStr(k.getMenuId())).collect(Collectors.toList());

        return Result.succeed(collect);
    }

    /**
     * roleCodes 其实是数据库中的role_alias
     * @param roleCodes
     * @return
     */
    @ApiOperation(value = "根据roleCodes获取对应的权限")
    @SuppressWarnings("unchecked")
    @Cacheable(value = "menu", key = "#roleCodes")
    @GetMapping("/{roleCodes}")
    public List<JsptMenu> findMenuByRoles(@PathVariable String roleCodes) {
        List<JsptMenu> result = null;
        if (StringUtils.isNotEmpty(roleCodes)) {
            Set<String> roleSet = (Set<String>) Convert.toCollection(HashSet.class, String.class, roleCodes);
            result = menuService.findByRoleCodes(roleSet, CommonConstant.PERMISSION);
        }
        return result;
    }

    /**
     * 给角色分配菜单
     */
    @ApiOperation(value = "角色分配菜单")
    @PostMapping("/granted")
    public Result setMenuToRole(@RequestBody JsptMenu jsptMenu) {
        menuService.setMenuToRole(jsptMenu.getRoleId(), jsptMenu.getMenuIds());
        return Result.succeed("操作成功");
    }

    /**
     * 两层循环实现建树
     *
     * @param jsptMenus
     * @return
     */
    public static List<JsptMenu> treeBuilder(List<JsptMenu> jsptMenus) {
        List<JsptMenu> menus = new ArrayList<>();
        for (JsptMenu jsptMenu : jsptMenus) {
            if (Objects.equals(-1L, jsptMenu.getParentId())) {
                menus.add(jsptMenu);
            }
            for (JsptMenu menu : jsptMenus) {
                if (menu.getParentId().equals(jsptMenu.getId())) {
                    if (jsptMenu.getChildren() == null) {
                        jsptMenu.setChildren(new ArrayList<>());
                    }
                    jsptMenu.getChildren().add(menu);
                }
            }
        }
        return menus;
    }
}
